Este projeto utiliza imagens como bases de dados, definindo seus pixels como cada linha e seus valores de R,G,B como cada coluna, qualquer imagem pode ser utilizada, o algoritimo K-Means sera utilizado para diminuir a quantidade de cores da imagem comprimindo-a, gerando uma imagem que ocupe menos espaço em disco.
O algoritimo K-Means pode ser treinado em uma imagem e utilizado para predizer a coloração de uma outra, gerando resultados interessantes que serão explorados ao longo do projeto em busca de possiveis aplicações para esse processamento.
Todas as imagens utilizadas para o processamento foram coletadas diretamente do Google images.
Numero de registros: As imagens utilizadas no projeto possuem resolução de 1920x1080, portanto 2073600 registros.
Quantidade de variaveis: 3
Dicionario de dados:
Quantidade de valores ausentes por variavel:
%matplotlib inline
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from sklearn.cluster import MiniBatchKMeans
import warnings; warnings.simplefilter('ignore')
%%javascript
IPython.OutputArea.prototype._should_scroll = function(lines) {
return false;
}
Os marcadores %matplotlib e %%javascript definem apenas opções de visualização de output do jupyter-notebook.
def get_colors(data):
shape_x, shape_y, shape_z = data.shape
data_scale = data / 255.0 # use 0...1 scale
return data_scale.reshape(shape_x * shape_y, shape_z)
def plot_pixels(data, title, colors=None, N=10000, fig=None, plot=(1,1,1)):
if colors is None:
colors = data
# choose a random subset
rng = np.random.RandomState(0)
i = rng.permutation(data.shape[0])[:N]
colors = colors[i]
R, G, B = data[i].T
if fig is None:
fig=plt.figure(figsize=(20,20))
ax = fig.add_subplot(*plot,projection='3d')
ax.scatter3D(R, G, B, color=colors, marker='.')
ax.set(xlabel='Red', ylabel='Green', zlabel='Blue', xlim=(0, 1), ylim=(0, 1), title=title)
def get_mmm(data):
return (np.mean(data), np.median(data), stats.mode(data, axis=None))
Carrega imagens a serem avaliadas.
img1_file = 'brasov.jpg'
img2_file = 'mountains.jpg'
img1 = plt.imread('images/'+img1_file)
fig=plt.figure(figsize=(20,10))
ax = fig.add_subplot(121)
ax.imshow(img1);
img2 = plt.imread('images/'+img2_file)
ax = fig.add_subplot(122)
ax.imshow(img2);
Adquire valores de media, mediana, moda e desvio padrão.
mean1, median1, modal1 = get_mmm(img1)
print('IMG1> Mean: '+str(mean1)+' Median:'+str(median1)+' Modal:'+str(modal1.mode)+' STD:'+str(np.std(img1)))
mean2, median2, modal2 = get_mmm(img2)
print('IMG2> Mean: '+str(mean2)+' Median:'+str(median2)+' Modal:'+str(modal2.mode)+' STD:'+str(np.std(img2)))
Nesta etapa sera processada a primeira imagem para treino do algoritimo K-Means em seguida utilizaremos o algoritimo treinado para predizer as versões com cores reduzidas da segunda imagem.
Nesta erapa executamos o algoritimo K-Means sobre a primeira imagem, para valores diferentes de clusters (16, 8, 4, 2) e testamos este resultado na segunda imagem.
# Original
img1_colors = get_colors(img1)
img2_colors = get_colors(img2)
# 16 Colors
img1_kmeans_16 = MiniBatchKMeans(16)
img1_kmeans_16.fit(img1_colors)
img1_16_colors = img1_kmeans_16.cluster_centers_[img1_kmeans_16.predict(img1_colors)]
img2_16_colors = img1_kmeans_16.cluster_centers_[img1_kmeans_16.predict(img2_colors)]
# 8 Colors
img1_kmeans_8 = MiniBatchKMeans(8)
img1_kmeans_8.fit(img1_colors)
img1_8_colors = img1_kmeans_8.cluster_centers_[img1_kmeans_8.predict(img1_colors)]
img2_8_colors = img1_kmeans_8.cluster_centers_[img1_kmeans_8.predict(img2_colors)]
# 4 Colors
img1_kmeans_4 = MiniBatchKMeans(4)
img1_kmeans_4.fit(img1_colors)
img1_4_colors = img1_kmeans_4.cluster_centers_[img1_kmeans_4.predict(img1_colors)]
img2_4_colors = img1_kmeans_4.cluster_centers_[img1_kmeans_4.predict(img2_colors)]
# 2 Colors
img1_kmeans_2 = MiniBatchKMeans(2)
img1_kmeans_2.fit(img1_colors)
img1_2_colors = img1_kmeans_2.cluster_centers_[img1_kmeans_2.predict(img1_colors)]
img2_2_colors = img1_kmeans_2.cluster_centers_[img1_kmeans_2.predict(img2_colors)]
Nesta etapa produzimos graficos sobre os resultados obtidos para o treino e teste do algoritimo K-Means.
fig=plt.figure(figsize=(20,40))
# Original
plot_pixels(img1_colors, title='Image color space: 16 million colors', fig=fig, plot=(5,2,1))
plot_pixels(img2_colors, title='Image color space: 16 million colors', fig=fig, plot=(5,2,2))
# 16 Colors
plot_pixels(img1_colors, colors=img1_16_colors,title="Reduced color space: 16 colors", fig=fig, plot=(5,2,3))
plot_pixels(img2_colors, colors=img2_16_colors,title="Predicted color space: 16 colors", fig=fig, plot=(5,2,4))
# 8 Colors
plot_pixels(img1_colors, colors=img1_8_colors,title="Reduced color space: 8 colors", fig=fig, plot=(5,2,5))
plot_pixels(img2_colors, colors=img2_8_colors,title="Predicted color space: 8 colors", fig=fig, plot=(5,2,6))
# 4 Colors
plot_pixels(img1_colors, colors=img1_4_colors,title="Reduced color space: 4 colors", fig=fig, plot=(5,2,7))
plot_pixels(img2_colors, colors=img2_4_colors,title="Predicted color space: 4 colors", fig=fig, plot=(5,2,8))
# 2 Colors
plot_pixels(img1_colors, colors=img1_2_colors,title="Reduced color space: 2 colors", fig=fig, plot=(5,2,9))
plot_pixels(img2_colors, colors=img2_2_colors,title="Predicted color space: 2 colors", fig=fig, plot=(5,2,10))
Nesta etapa transformamos o array de cores da imagem de volta no formato de imagem.
# 16 Colors
img1_16 = img1_16_colors.reshape(img1.shape)
img2_16 = img2_16_colors.reshape(img2.shape)
# 8 Colors
img1_8 = img1_8_colors.reshape(img1.shape)
img2_8 = img2_8_colors.reshape(img2.shape)
# 4 Colors
img1_4 = img1_4_colors.reshape(img1.shape)
img2_4 = img2_4_colors.reshape(img2.shape)
# 2 Colors
img1_2 = img1_2_colors.reshape(img1.shape)
img2_2 = img2_2_colors.reshape(img2.shape)
Nesta etapa comparamos as imagens preditas pelo teste com as imagens obtidas durante o treino.
fig, ax = plt.subplots(5, 2, figsize=(20, 30),subplot_kw=dict(xticks=[], yticks=[]))
# Original
ax[0][0].set_title('Original Image', size=16)
ax[0][0].imshow(img1)
ax[0][1].set_title('Original Image', size=16)
ax[0][1].imshow(img2)
# 16 Colors
ax[1][0].set_title('16-color Image', size=16)
ax[1][0].imshow(img1_16)
ax[1][1].set_title('Predicted 16-color Image', size=16)
ax[1][1].imshow(img2_16)
# 8 Colors
ax[2][0].set_title('8-color Image', size=16)
ax[2][0].imshow(img1_8)
ax[2][1].set_title('Predicted 8-color Image', size=16)
ax[2][1].imshow(img2_8)
# 4 Colors
ax[3][0].set_title('4-color Image', size=16)
ax[3][0].imshow(img1_4)
ax[3][1].set_title('Predicted 4-color Image', size=16)
ax[3][1].imshow(img2_4)
# 2 Colors
ax[4][0].set_title('2-color Image', size=16)
ax[4][0].imshow(img1_2)
ax[4][1].set_title('Predicted 2-color Image', size=16)
ax[4][1].imshow(img2_2)
Nesta etapa comparamos a clusterização da segunda imagem a partir do treino com a primeira imagem e com o treino sobre si mesma, assim podemos comparar os resultados que foram gerados com as que eram esperados.
# 16 Colors
img2_kmeans_16 = MiniBatchKMeans(16)
img2_kmeans_16.fit(img2_colors)
img2_16_colors_fixed = img2_kmeans_16.cluster_centers_[img2_kmeans_16.predict(img2_colors)]
# 8 Colors
img2_kmeans_8 = MiniBatchKMeans(8)
img2_kmeans_8.fit(img2_colors)
img2_8_colors_fixed = img2_kmeans_8.cluster_centers_[img2_kmeans_8.predict(img2_colors)]
# 4 Colors
img2_kmeans_4 = MiniBatchKMeans(4)
img2_kmeans_4.fit(img2_colors)
img2_4_colors_fixed = img2_kmeans_4.cluster_centers_[img2_kmeans_4.predict(img2_colors)]
# 2 Colors
img2_kmeans_2 = MiniBatchKMeans(2)
img2_kmeans_2.fit(img2_colors)
img2_2_colors_fixed = img2_kmeans_2.cluster_centers_[img2_kmeans_2.predict(img2_colors)]
fig=plt.figure(figsize=(20,30))
# 16 Colors
plot_pixels(img2_colors, colors=img2_16_colors_fixed,title="Correct color space: 16 colors", fig=fig, plot=(4,2,1))
plot_pixels(img2_colors, colors=img2_16_colors,title="Predicted color space: 16 colors", fig=fig, plot=(4,2,2))
# 8 Colors
plot_pixels(img2_colors, colors=img2_8_colors_fixed,title="Correct color space: 8 colors", fig=fig, plot=(4,2,3))
plot_pixels(img2_colors, colors=img2_8_colors,title="Predicted color space: 8 colors", fig=fig, plot=(4,2,4))
# 4 Colors
plot_pixels(img2_colors, colors=img2_4_colors_fixed,title="Correct color space: 4 colors", fig=fig, plot=(4,2,5))
plot_pixels(img2_colors, colors=img2_4_colors,title="Predicted color space: 4 colors", fig=fig, plot=(4,2,6))
# 2 Colors
plot_pixels(img2_colors, colors=img2_2_colors_fixed,title="Correct color space: 2 colors", fig=fig, plot=(4,2,7))
plot_pixels(img2_colors, colors=img2_2_colors,title="Predicted color space: 2 colors", fig=fig, plot=(4,2,8))
Nesta etapa representamos os valores dos graficos da etapa 5.5. em forma de imagem para melhor visualização.
# 16 Colors
img2_16_fixed = img2_16_colors_fixed.reshape(img2.shape)
# 8 Colors
img2_8_fixed = img2_8_colors_fixed.reshape(img2.shape)
# 4 Colors
img2_4_fixed = img2_4_colors_fixed.reshape(img2.shape)
# 2 Colors
img2_2_fixed = img2_2_colors_fixed.reshape(img2.shape)
fig, ax = plt.subplots(4, 2, figsize=(20, 20),subplot_kw=dict(xticks=[], yticks=[]))
# 16 Colors
ax[0][0].set_title('Correct 16-color Image', size=16)
ax[0][0].imshow(img2_16_fixed)
ax[0][1].set_title('Predicted 16-color Image', size=16)
ax[0][1].imshow(img2_16)
# 8 Colors
ax[1][0].set_title('Correct 8-color Image', size=16)
ax[1][0].imshow(img2_8_fixed)
ax[1][1].set_title('Predicted 8-color Image', size=16)
ax[1][1].imshow(img2_8)
# 4 Colors
ax[2][0].set_title('Correct 4-color Image', size=16)
ax[2][0].imshow(img2_4_fixed)
ax[2][1].set_title('Predicted 4-color Image', size=16)
ax[2][1].imshow(img2_4)
# 2 Colors
ax[3][0].set_title('Correct 2-color Image', size=16)
ax[3][0].imshow(img2_2_fixed)
ax[3][1].set_title('Predicted 2-color Image', size=16)
ax[3][1].imshow(img2_2)
Ao executar o algoritimo K-Means sobre os pixels de uma imagem separamos em clusters os pixels de acordo com as suas cores, dessa maneira podemos definir a todos os membros de um cluster um so valor de R, G, B, reduzindo o numero de cores na imagem, tornando menor o espaço necessario para armazenamento.
Ao treinar o algoritimo com uma imagem e aplica-lo em outra nota-se que as cores da imagem que treinou o algoritimo são aplicadas sobre as cores da segunda imagem efetivemante substituindo sua paleta de cores pela paleta de cores da primeira. O algoritimo tenta predizer qual seria as cores da forma reduzida da segunda imagem utilizando cores geradas a partir da primeira, a cor mais proxima da sua paleta de cores sera aplicada no lugar da cor da segunda imagem.
Se compararmos a quantidade de detalhes apresentados na segunda imagem quando gerada a partir de sua propria paleta e quando gerada a partir da paleta da primeira imagem, notamos que ambas evidenciam diferentes detalhes e bordas na imagem.
Futuramente pretendo treinar o algoritimo com um maior numero de imagens e fazer associações com os resultados obtidos, pretendo encontrar padrões de cores em certas categorias de imagens e combinar os resultados de diferentes paletas aplicadas a uma imagem para evidenciar atributos da imagem. Vou explorar outras ideias com o desenrolar do projeto, espero encontrar ainda mais possiveis associações para serem feitas com os dados obtidos.